//package cn.tqfeiyang.springplus.system.logging;
//
//import cn.tqfeiyang.springplus.framework.logging.LogRequirement;
//import cn.tqfeiyang.springplus.framework.security.SecurityService;
//import cn.tqfeiyang.springplus.framework.toolkit.NetworkUtils;
//import cn.tqfeiyang.springplus.framework.toolkit.ServletUtils;
//import cn.tqfeiyang.springplus.system.entity.LogEntity;
//import cn.tqfeiyang.springplus.system.mapper.LogMapper;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.json.JsonMapper;
//import io.swagger.v3.oas.annotations.Operation;
//import jakarta.annotation.Resource;
//import jakarta.servlet.http.HttpServletRequest;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.annotation.*;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.slf4j.event.Level;
//import org.springframework.stereotype.Component;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.bind.annotation.RequestParam;
//
//import java.io.PrintWriter;
//import java.io.StringWriter;
//import java.lang.reflect.Method;
//import java.lang.reflect.Parameter;
//import java.time.LocalDateTime;
//import java.time.ZoneId;
//import java.util.*;
//import java.time.Instant;
//
///**
// * 标记了 @LoggingRequirement 的控制器方法，允许保存事务日志到数据库。
// *
// * 通过 MethodLoggingAspect 实现。
// *
// * @author tqfeiyang
// * @since 2024-07-19
// */
//@Slf4j
//@Aspect
//@Component
//public class MethodLoggingAspect {
//
//    @Resource
//    private SecurityService securityService;
//
//    @Resource
//    private LogMapper logMapper;
//
//    ThreadLocal<Long> currentTime = new ThreadLocal<>();
//
//    @Pointcut("@annotation(cn.tqfeiyang.springplus.framework.logging.LoggingRequirement)")
//    public void logPointcut() {}
//
//    @Before("logPointcut()")
//    public void logBefore() {
//        currentTime.set(System.currentTimeMillis());
//    }
//
//    @AfterReturning(pointcut = "logPointcut()")
//    public void logAfterReturning(JoinPoint joinPoint) {
//        saveLog(joinPoint, Level.INFO, currentTime.get(), System.currentTimeMillis(), null);
//    }
//
//    @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
//    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
//        saveLog(joinPoint, Level.ERROR, currentTime.get(), System.currentTimeMillis(), e);
//    }
//
//    private void saveLog(JoinPoint joinPoint, Level level, Long startTime, Long finishTime, Throwable throwable) {
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//
//        LogEntity logEntity = new LogEntity();
//        logEntity.setLevel(level.name());
//        logEntity.setUserId(securityService.getUserId());
//        logEntity.setOperation(getMethodOperation(signature.getMethod()));
//        logEntity.setResult(throwable != null ? "失败" : "成功");
//        logEntity.setArguments(getMethodArguments(signature.getMethod(), joinPoint.getArgs()));
//        logEntity.setExceptionDetail(getStackTrace(throwable));
//        logEntity.setStartTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(startTime), ZoneId.systemDefault()));
//        logEntity.setFinishTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(finishTime), ZoneId.systemDefault()));
//        logEntity.setElapsedTime(finishTime - startTime);
//        logEntity.setController(joinPoint.getTarget().getClass().getName());
//        logEntity.setMethod(signature.getName());
//
//        HttpServletRequest request = ServletUtils.getRequest();
//        logEntity.setClientIp(NetworkUtils.getRequestIp(request));
//        logEntity.setRequestUri(request.getRequestURI());
//
//        logMapper.insert(logEntity);
//    }
//
//    private String getMethodOperation(Method method) {
//        LogRequirement logAnnotation = method.getAnnotation(LogRequirement.class);
//        if (Objects.nonNull(logAnnotation) && StringUtils.hasText(logAnnotation.value())) {
//            return logAnnotation.value();
//        }
//
//        Operation operationAnnotation = method.getAnnotation(Operation.class);
//        if (Objects.nonNull(operationAnnotation) && StringUtils.hasText(operationAnnotation.summary())) {
//            return operationAnnotation.summary();
//        }
//
//        return method.getName();
//    }
//
//    private String getMethodArguments(Method method, Object[] args) {
//        Parameter[] parameters = method.getParameters();
//        if (ObjectUtils.isEmpty(parameters)) {
//            return null;
//        }
//
//        Map<String, Object> arguments = new HashMap<>();
//
//        for (int i = 0; i < parameters.length; i++) {
//            arguments.put(parameters[i].getName(), args[i]);
//        }
//
//        try {
//            JsonMapper jsonMapper = new JsonMapper();
//            return jsonMapper.writeValueAsString(arguments);
//        } catch (JsonProcessingException e) {
//            throw new RuntimeException(e);
//        }
//    }
//
//    private String getMethodArgumentsAAA(Method method, Object[] args) {
//        List<Object> argList = new ArrayList<>();
//        Parameter[] parameters = method.getParameters();
//
//        for (int i = 0; i < parameters.length; i++) {
//            //将RequestBody注解修饰的参数作为请求参数
//            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
//            if (requestBody != null) {
//                argList.add(args[i]);
//            }
//
//            //将RequestParam注解修饰的参数作为请求参数
//            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
//            if (requestParam != null) {
//                Map<String, Object> map = new HashMap<>(4);
//                String key = parameters[i].getName();
//                if (StringUtils.hasText(requestParam.value())) {
//                    key = requestParam.value();
//                }
//                map.put(key, args[i]);
//                argList.add(map);
//            }
//        }
//
//        if (argList.isEmpty()) {
//            return "";
//        }
//
//        JsonMapper jsonMapper = new JsonMapper();
//        try {
//            return argList.size() == 1 ?
//                    jsonMapper.writeValueAsString(argList.get(0)) : jsonMapper.writeValueAsString(argList);
//        } catch (JsonProcessingException e) {
//            throw new RuntimeException(e);
//        }
//    }
//
//    public static String getStackTrace(Throwable throwable){
//        if (throwable == null) {
//            return "";
//        }
//
//        StringWriter sw = new StringWriter();
//        try (PrintWriter pw = new PrintWriter(sw)) {
//            throwable.printStackTrace(pw);
//            return sw.toString();
//        }
//    }
//}
